home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 431_01 / rclient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-06  |  26.7 KB  |  1,056 lines

  1. /*
  2.   this program will have two simple functions.
  3.     CLIENT
  4.       1. check IFS request. if not for my drives, pass on
  5.       2. packet the request for xfer
  6.       3. xfer packet. wait for return
  7.       4. unpacket the result
  8.       5. return
  9. */
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <dir.h>
  15. #include <dos.h>
  16.  
  17. #include "ifs.h"
  18. #include "comio.h"
  19. #include "crc32.h"
  20. #include "svr0.h"
  21. #include "ifs0.h"
  22. #include "rifs.h"
  23. #include "myalloc.h"
  24. #include "rclient.h"
  25.  
  26. #include "local.h"
  27. unsigned _stklen=512;
  28.  
  29. LOCAL BYTE    *SDA;         /* swappable data area         */
  30. LOCAL WORD     SDA_maxsize; /* size of SDA                 */
  31. LOCAL WORD     SDA_minsize;
  32. LOCAL BYTE    *CDS_base;    /* current directory structure */
  33. LOCAL WORD     CDS_size;    /* # of bytes per entry        */
  34. LOCAL WORD     CDS_ct;      /* number of entries           */
  35.  
  36. /*************************************************************************
  37.  *************************************************************************
  38.   CLIENT
  39.  *************************************************************************
  40.  *************************************************************************/
  41. /*
  42.   these are the sda members about which i am concerned
  43.   (set on entry)
  44. */
  45. LOCAL WORD  *SDA_CURR_PSP;
  46. LOCAL DTA  **SDA_CURR_DTA;
  47. LOCAL char  *SDA_FN1;
  48. LOCAL char  *SDA_FN2;
  49. LOCAL SDB   *SDA_SDB;
  50. LOCAL CDS   *SDA_CURR_CDS;
  51. LOCAL DIR   *SDA_DIR_ENTRY;
  52. LOCAL BYTE  *SDA_SRCH_ATTR;
  53. LOCAL BYTE  *SDA_OPEN_MODE;
  54. LOCAL CDS  **SDA_DRIVE_CDSPTR;
  55. LOCAL SFT  **SDA_SFT;
  56. LOCAL WORD  *SDA_EXTOPEN_ACTION;
  57. LOCAL WORD  *SDA_EXTOPEN_ATTR;
  58. LOCAL WORD  *SDA_EXTOPEN_MODE;
  59.  
  60. LOCAL CDS     *CDS_init;          /* initial CDS structure       */
  61. LOCAL XMITBUF *iobuf1,            /* current / last used buffers */
  62.               *iobuf2,
  63.               *iobufptr;          /* current buffer        */
  64. LOCAL WORD     iobufptr_datasize; /* i/o data buffer size  */
  65. LOCAL WORD     iobufptr_rwdatasize; /* largest block to send for read/write
  66.                                        must be no bigger than datasize-8  */
  67. LOCAL BYTE     remote;            /* remote drive map      */
  68. LOCAL BYTE     local;             /* local drive           */
  69.  
  70. /*
  71.   drive translation table
  72.   0 = not mapped, else 'A'..'Z' is translation
  73.   ex:
  74.     SVR_XLAT_TABLE[3] == 'C'
  75.       then local drive D is mapped to server drive C
  76. */
  77. LOCAL BYTE DRIVE_XLAT_TABLE[26];
  78.  
  79. LOCAL IFS_STAT IFS_stat;
  80.  
  81.  
  82. LOCAL BYTE portmapped[3];
  83.  
  84. BOOL portio(INTREGS *regs);
  85.  
  86. int Intr17(INTREGS *regs)
  87. {
  88.   if ((regs->dx < 3) && (regs->ax < 0x300) && portmapped[regs->dx]) {
  89.     WORD oldport = regs->dx;
  90.     regs->dx=portmapped[regs->dx]-1;
  91.     portio(regs);
  92.     regs->dx=oldport;
  93. /*
  94.     if (regs->ax)
  95.       regs->flags |= 0x40;
  96.     else
  97.       regs->flags &= ~0x40;
  98. */
  99.     return 1;
  100.   } else
  101.     return 0;
  102. }
  103.  
  104. LOCAL void uninit(void)
  105. {
  106.   ifs0_shutdown();
  107.   CommIO_shutdown();
  108.   if (CDS_init) {
  109.     memcpy(CDS_base, CDS_init, CDS_size * CDS_ct);
  110.     my_free(CDS_init);
  111.     CDS_init=0;
  112.   }
  113.   if (iobuf1) {
  114.     my_free(iobuf1);
  115.     my_free(iobuf2);
  116.     iobufptr=0;
  117.     iobufptr_datasize=0;
  118.   }
  119. }
  120.  
  121. /*
  122.   initialize misc-> varaibles
  123. */
  124. LOCAL BOOL InitClient(int intno)
  125. {
  126.   struct REGPACK regs;
  127.   BYTE *LOL; /* list of lists       */
  128.  
  129.   regs.r_ax=0x5d06;
  130.   intr(0x21, ®s);
  131.   SDA=MK_FP(regs.r_ds, regs.r_si);
  132.   SDA_maxsize=regs.r_cx;
  133.   SDA_minsize=regs.r_dx;
  134.  
  135.   /*
  136.     init lcl_SDA (for SERVER)
  137.   */
  138.   regs.r_ax=0x5200;
  139.   intr(0x21, ®s);
  140.   LOL=MK_FP(regs.r_es, regs.r_bx);
  141.  
  142.   CDS_base=*(void **) (LOL+0x16);
  143.   CDS_ct=*(BYTE *) (LOL + 0x21);
  144.  
  145.   if (_osmajor >= 5) {
  146.     CDS_size           = 0x58;
  147.     SDA_CURR_DTA       = (void *) (SDA + 0x000c);
  148.     SDA_CURR_PSP       = (void *) (SDA + 0x0010);
  149.     SDA_FN1            = (void *) (SDA + 0x009e);
  150.     SDA_FN2            = (void *) (SDA + 0x011e);
  151.     SDA_SDB            = (void *) (SDA + 0x019e);
  152.     SDA_DIR_ENTRY      = (void *) (SDA + 0x01b3);
  153.     SDA_CURR_CDS       = (void *) (SDA + 0x01d3);
  154.     SDA_SRCH_ATTR      = (void *) (SDA + 0x024d);
  155.     SDA_OPEN_MODE      = (void *) (SDA + 0x024e);
  156.     SDA_SFT            = (void *) (SDA + 0x027e);
  157.     SDA_DRIVE_CDSPTR   = (void *) (SDA + 0x0282);
  158.     SDA_EXTOPEN_ACTION = (void *) (SDA + 0x02dd);
  159.     SDA_EXTOPEN_ATTR   = (void *) (SDA + 0x02df);
  160.     SDA_EXTOPEN_MODE   = (void *) (SDA + 0x02e1);
  161.   } else {
  162.     CDS_size           = 0x51;
  163.     SDA_CURR_DTA       = (void *) (SDA + 0x000c);
  164.     SDA_CURR_PSP       = (void *) (SDA + 0x0010);
  165.     SDA_FN1            = (void *) (SDA + 0x0092);
  166.     SDA_FN2            = (void *) (SDA + 0x0112);
  167.     SDA_SDB            = (void *) (SDA + 0x0192);
  168.     SDA_DIR_ENTRY      = (void *) (SDA + 0x01a7);
  169.     SDA_CURR_CDS       = (void *) (SDA + 0x01c7);
  170.     SDA_SRCH_ATTR      = (void *) (SDA + 0x023a);
  171.     SDA_OPEN_MODE      = (void *) (SDA + 0x023b);
  172.     SDA_SFT            = (void *) (SDA + 0x0268);
  173.     SDA_DRIVE_CDSPTR   = (void *) (SDA + 0x026c);
  174.     SDA_EXTOPEN_ACTION = 0; /* these do not exist in DOS 3.x */
  175.     SDA_EXTOPEN_ATTR   = 0;
  176.     SDA_EXTOPEN_MODE   = 0;
  177.   }
  178.   ifs0_init(intno);
  179.  
  180.   CDS_init=my_malloc(CDS_size * CDS_ct);
  181.   memcpy(CDS_init, CDS_base, CDS_size * CDS_ct);
  182.  
  183.   iobufptr_datasize=BLOCKSIZE;
  184.   iobufptr_rwdatasize=BLOCKSIZE-8;
  185.   iobuf1=my_malloc(iobufptr_datasize+sizeof(*iobuf1));
  186.   iobuf2=my_malloc(iobufptr_datasize+sizeof(*iobuf2));
  187.   iobufptr=iobuf1;
  188.  
  189.   return 1;
  190. }
  191.  
  192. #define COMMAND(a) {iobufptr->length=0; iobufptr->cmd=a; }
  193. #define SPARAM(a) {strcpy(iobufptr->data+iobufptr->length, a); iobufptr->length+=strlen(a)+1; }
  194.  
  195. WORD Transmit(void);
  196.  
  197. /*
  198.   port i/o
  199.     dx = port # (0..2, 0x80..0x83)
  200.     ah = function #
  201.     al = character
  202. */
  203. LOCAL BOOL portio(INTREGS *regs)
  204. {
  205.   COMMAND(IFS_PORTOUT);
  206.   *(WORD *) iobufptr->data = regs->dx;
  207.   *(WORD *) (iobufptr->data+2) = regs->ax;
  208.   iobufptr->length = 4;
  209.   Transmit();
  210.   regs->ax=iobufptr->cmd;
  211.   return (regs->ax) ? 0xff00 : 0x0000;
  212. }
  213. /*
  214.   remove directory
  215. */
  216. LOCAL BOOL ifs_rmdir(INTREGS *regs)
  217. {
  218.   COMMAND(IFS_RMDIR);
  219.   SPARAM(SDA_FN1);
  220.   iobufptr->data[0]=remote;
  221.   Transmit();
  222.   regs->ax=iobufptr->cmd;
  223.   return (regs->ax) ? 0xff00 : 0x0000;
  224. }
  225.  
  226. /*
  227.   change directory
  228. */
  229. LOCAL BOOL ifs_chdir(INTREGS *regs)
  230. {
  231.   COMMAND(IFS_CHDIR);
  232.   SPARAM(SDA_FN1);
  233.   iobufptr->data[0]=remote;
  234.   Transmit();
  235.   regs->ax=iobufptr->cmd;
  236.   return (regs->ax) ? 0xff00 : 0x0000;
  237. }
  238.  
  239. /*
  240.   create directory
  241. */
  242. LOCAL BOOL ifs_mkdir(INTREGS *regs)
  243. {
  244.   COMMAND(IFS_MKDIR);
  245.   SPARAM(SDA_FN1);
  246.   iobufptr->data[0]=remote;
  247.   Transmit();
  248.   regs->ax=iobufptr->cmd;
  249.   return (regs->ax) ? 0xff00 : 0x0000;
  250. }
  251.  
  252. LOCAL BOOL ifs_closefile(INTREGS *regs)
  253. {
  254.   SFT *sft=MK_FP(regs->es, regs->di);
  255.  
  256.   COMMAND(IFS_CLOSEFILE);
  257.   *(int *) iobufptr->data=sft->dir_sector;
  258.   *(unsigned *) (iobufptr->data+2) = sft->ftime;
  259.   *(unsigned *) (iobufptr->data+4) = sft->fdate;
  260.   iobufptr->length=6;
  261.   Transmit();
  262.  
  263.   if (sft->handlect > 0)
  264.     sft->handlect--;
  265.  
  266.   regs->ax=iobufptr->cmd;
  267.   return (regs->ax) ? 0xff00 : 0x0000;
  268. }
  269.  
  270. LOCAL BOOL ifs_commitfile(INTREGS *regs)
  271. {
  272.   COMMAND(IFS_COMMITFILE);
  273.   Transmit();
  274.   regs->ax=iobufptr->cmd;
  275.   return (regs->ax) ? 0xff00 : 0x0000;
  276. }
  277.  
  278. #define NORMALIZE(a) a=MK_FP(FP_SEG(a)+(FP_OFF(a) >> 4), FP_OFF(a) & 0x0f)
  279.  
  280. LOCAL BOOL ifs_readfile(INTREGS *regs)
  281. {
  282.   SFT *sft=MK_FP(regs->es, regs->di);
  283.   char *dst=(char *) *SDA_CURR_DTA;
  284.   WORD  sz=regs->cx;
  285.   int   read;
  286.  
  287.   regs->cx=0;
  288.   while (sz > 0) {
  289.     int tz=min(iobufptr_rwdatasize, sz);
  290.  
  291.     COMMAND(IFS_READFILE);
  292.     *(int  *) iobufptr->data    =sft->dir_sector;
  293.     *(long *) (iobufptr->data+2)=sft->fpos;
  294.     *(int  *) (iobufptr->data+6)=tz;
  295.     iobufptr->length=8;
  296.  
  297.     Transmit();
  298.  
  299.     read=*(int *) iobufptr->data;
  300.     memcpy(dst, iobufptr->data+2, read);
  301.  
  302.     dst += read;
  303.     NORMALIZE(dst);
  304.  
  305.     sz -= read;
  306.     regs->cx += read;
  307.  
  308.     regs->ax=iobufptr->cmd;
  309.  
  310.     sft->fpos += read;
  311.  
  312.     if ((regs->ax != 0) || (read != tz))
  313.       break;
  314.   }
  315.   return (regs->ax) ? 0xff00 : 0x0000;
  316. }
  317.  
  318. LOCAL BOOL ifs_writefile(INTREGS *regs)
  319. {
  320.   SFT *sft=MK_FP(regs->es, regs->di);
  321.   char *src=(char *) *SDA_CURR_DTA;
  322.   WORD  sz=regs->cx;
  323.   int   trunc = (regs->cx == 0); /* if write length is 0, truncate file */
  324.   int   written;
  325.  
  326.   regs->cx=0;
  327.   while ((sz > 0) | trunc) {
  328.     int tz=min(iobufptr_rwdatasize, sz); /* 8 = size of return header */
  329.  
  330.     COMMAND(IFS_WRITEFILE);
  331.     *(int  *) iobufptr->data     = sft->dir_sector;
  332.     *(long *) (iobufptr->data+2) = sft->fpos;
  333.     *(int  *) (iobufptr->data+6) = tz;
  334.     iobufptr->length=8;
  335.     if (tz) {
  336.       memcpy(iobufptr->data+iobufptr->length, src, tz);
  337.       iobufptr->length+=tz;
  338.     } else
  339.       trunc=0;
  340.     Transmit();
  341.  
  342.     written=*(int *) iobufptr->data;
  343.     src += written;
  344.     NORMALIZE(src);
  345.     sz -= *(int *)  iobufptr->data;
  346.     regs->cx += written;
  347.  
  348.     regs->ax=iobufptr->cmd;
  349.  
  350.     sft->fpos += written;
  351.     sft->fsize = max(sft->fsize, sft->fpos);
  352.     sft->dev_info &= ~0x0040;
  353.  
  354.     /*
  355.       on error or partial, break
  356.     */
  357.     if ((regs->ax != 0) || (written != tz))
  358.       break;
  359.   }
  360.   return (regs->ax) ? 0xff00 : 0x0000;
  361. }
  362.  
  363. LOCAL BOOL ifs_lockfile(INTREGS *regs)
  364. {
  365.   regs->ax=0x05;
  366.   return (regs->ax) ? 0xff00 : 0x0000;
  367. }
  368.  
  369. LOCAL BOOL ifs_unlockfile(INTREGS *regs)
  370. {
  371.   regs->ax=0x05;
  372.   return (regs->ax) ? 0xff00 : 0x0000;
  373. }
  374.  
  375. LOCAL BOOL ifs_getspace(INTREGS *regs)
  376. {
  377.   struct dfree *df;
  378.   COMMAND(IFS_GETSPACE);
  379.   *(BYTE *) iobufptr->data=(remote-'A'+1);
  380.   iobufptr->length=1;
  381.   Transmit();
  382.   regs->ax=iobufptr->cmd;
  383.   df=(void *) iobufptr->data;
  384.   regs->ax=df->df_sclus;
  385.   regs->bx=df->df_total;
  386.   regs->cx=df->df_bsec;
  387.   regs->dx=df->df_avail;
  388.   return 0;
  389. }
  390.  
  391. LOCAL BOOL ifs_setattr(INTREGS *regs)
  392. {
  393.   COMMAND(IFS_SETATTR);
  394.   *(WORD *) (iobufptr->data)=regs->wparam;
  395.   iobufptr->length=2;
  396.   SPARAM(SDA_FN1);
  397.   iobufptr->data[2]=remote;
  398.   Transmit();
  399.   regs->ax=iobufptr->cmd;
  400.   return (regs->ax) ? 0xff00 : 0x0000;
  401. }
  402.  
  403. LOCAL BOOL ifs_getattr(INTREGS *regs)
  404. {
  405.   COMMAND(IFS_GETATTR);
  406.   SPARAM(SDA_FN1);
  407.   iobufptr->data[0]=remote;
  408.   Transmit();
  409.   regs->ax=*(WORD *) iobufptr->data;
  410.   return (iobufptr->cmd) ? 0xff00 : 0x0000;
  411. }
  412.  
  413. LOCAL BOOL ifs_renamefile(INTREGS *regs)
  414. {
  415.   char *ptr;
  416.  
  417.   COMMAND(IFS_RENAMEFILE);
  418.   SPARAM(SDA_FN1);
  419.   iobufptr->data[0]=remote;
  420.   ptr=iobufptr->data+iobufptr->length;
  421.   SPARAM(SDA_FN2);
  422.   *ptr=remote;
  423.   Transmit();
  424.   regs->ax=iobufptr->cmd;
  425.   return (regs->ax) ? 0xff00 : 0x0000;
  426. }
  427.  
  428. LOCAL BOOL ifs_deletefile(INTREGS *regs)
  429. {
  430.   COMMAND(IFS_DELETEFILE);
  431.   SPARAM(SDA_FN1);
  432.   iobufptr->data[0]=remote;
  433.   Transmit();
  434.   regs->ax=iobufptr->cmd;
  435.   return (regs->ax) ? 0xff00 : 0x0000;
  436. }
  437.  
  438. LOCAL void NAMEtoFCB(char *name, char fcb[11])
  439. {
  440.   memset(fcb, ' ', 11);
  441.   if (name[0] == '.')
  442.     memcpy(fcb, name, strlen(name));
  443.   else {
  444.     int ii;
  445.     char *ptr;
  446.  
  447.     for (ii=strlen(name)-1;
  448.          (ii >= 0) &&
  449.          (name[ii] != ':') &&
  450.          (name[ii] != '\\');
  451.          ii--);
  452.     ii++;
  453.     ptr=name+ii;
  454.  
  455.     for (ii=0; ii < 8; ii++)
  456.       fcb[ii] = (*ptr && (*ptr != '.')) ? *(ptr++) : ' ';
  457.     if (*ptr == '.')
  458.       ptr++;
  459.     for (ii=8; ii < 11; ii++)
  460.       fcb[ii] = (*ptr) ? *(ptr++) : ' ';
  461.   }
  462. }
  463.  
  464. LOCAL BOOL ifs_openfile(INTREGS *regs)
  465. {
  466.   SFT *sft=MK_FP(regs->es, regs->di);
  467.   char *ptr;
  468.  
  469.   memset(sft, 0, sizeof(*sft));
  470.   sft->handlect=1; /* see ifs_extopen() */
  471.   COMMAND(IFS_OPENFILE);
  472.   *(int *) iobufptr->data = *SDA_OPEN_MODE;
  473.   iobufptr->length=2;
  474.   ptr=iobufptr->data+iobufptr->length;
  475.   SPARAM(SDA_FN1);
  476.   *ptr=remote;
  477.   Transmit();
  478.   regs->ax=iobufptr->cmd;
  479.   if (regs->ax == 0) {
  480.     sft->dir_sector=*(int *) iobufptr->data; /* this is really the file handle */
  481.     sft->open_mode=*SDA_OPEN_MODE;
  482.     sft->attr     =*(int *) (iobufptr->data+2);
  483.     sft->dev_info=0x8040 | (local-'A'+1); /* force drive Z */
  484.     sft->ftime    = *(int *) (iobufptr->data+4);
  485.     sft->fdate    = *(int *) (iobufptr->data+6);
  486.     sft->fsize    = *(long *) (iobufptr->data+8);
  487.     NAMEtoFCB(SDA_FN1, sft->fcb_name);
  488.   }
  489.   return (regs->ax) ? 0xff00 : 0x0000;
  490. }
  491.  
  492. LOCAL BOOL ifs_createfile(INTREGS *regs)
  493. {
  494.   SFT *sft=MK_FP(regs->es, regs->di);
  495.   char *ptr;
  496.  
  497.   memset(sft, 0, sizeof(*sft));
  498.   sft->handlect=1; /* see ifs_extopen() */
  499.   COMMAND(IFS_CREATEFILE);
  500.   *(int *) iobufptr->data=regs->wparam;
  501.   iobufptr->length=2;
  502.   ptr=iobufptr->data+iobufptr->length;
  503.   SPARAM(SDA_FN1);
  504.   *ptr=remote;
  505.   Transmit();
  506.   sft->handlect=0;
  507.   regs->ax=iobufptr->cmd;
  508.   if (regs->ax == 0) {
  509.     sft->dir_sector=*(int *) iobufptr->data; /* this is really the file handle */
  510.     sft->open_mode=0x02;
  511.     sft->attr     =*(int *) (iobufptr->data+2);
  512.     sft->dev_info=0x8040 | (local-'A'+1);
  513.     sft->ftime    = *(int *) (iobufptr->data+4);
  514.     sft->fdate    = *(int *) (iobufptr->data+6);
  515.     sft->fsize    = *(long *) (iobufptr->data+8);
  516.     NAMEtoFCB(SDA_FN1, sft->fcb_name);
  517.   }
  518.   return (regs->ax) ? 0xff00 : 0x0000;
  519. }
  520.  
  521. LOCAL void DTAtoDIR(struct ffblk *ffblk)
  522. {
  523.   NAMEtoFCB(ffblk->ff_name, SDA_DIR_ENTRY->fname);
  524.   SDA_DIR_ENTRY->attr  = ffblk->ff_attrib;
  525.   SDA_DIR_ENTRY->ftime = ffblk->ff_ftime;
  526.   SDA_DIR_ENTRY->fdate = ffblk->ff_fdate;
  527.   SDA_DIR_ENTRY->cluster=0;
  528.   SDA_DIR_ENTRY->size  = ffblk->ff_fsize;
  529. }
  530.  
  531. LOCAL BOOL ifs_findfirst(INTREGS *regs)
  532. {
  533.   char *ptr;
  534.  
  535.   COMMAND(IFS_FINDFIRST);
  536.   *(int *) iobufptr->data=*SDA_SRCH_ATTR;
  537.   iobufptr->length=2;
  538.   ptr=iobufptr->data+iobufptr->length;
  539.   SPARAM(SDA_FN1);
  540.   *ptr=remote;
  541.  
  542.   Transmit();
  543.   regs->ax=iobufptr->cmd;
  544.  
  545.   {
  546.     struct ffblk *ffblk=(struct ffblk *) iobufptr->data;
  547.     iobufptr->data[0]=(remote-'A'+1);
  548.     memcpy(*SDA_CURR_DTA, ffblk, sizeof(*ffblk));
  549.     memcpy(SDA_SDB, ffblk, sizeof(*SDA_SDB));
  550.     SDA_SDB->drive |= 0x80;
  551.     DTAtoDIR(ffblk);
  552.   }
  553.  
  554.   return (regs->ax) ? 0xff00 : 0x0000;
  555. }
  556.  
  557. /*
  558.   packet:
  559.     word = FINDNEXT
  560.   result:
  561.     word = result
  562. */
  563. LOCAL BOOL ifs_findnext(INTREGS *regs)
  564. {
  565.   COMMAND(IFS_FINDNEXT);
  566.  
  567.   memcpy(iobufptr->data, *SDA_CURR_DTA, sizeof(**SDA_CURR_DTA));
  568.   iobufptr->length=sizeof(**SDA_CURR_DTA);
  569.   iobufptr->data[0] = (remote-'A'+1);
  570.   Transmit();
  571.   regs->ax = iobufptr->cmd;
  572.  
  573.   {
  574.     struct ffblk *ffblk=(struct ffblk *) iobufptr->data;
  575.     iobufptr->data[0]=(remote-'A'+1);
  576.     memcpy(*SDA_CURR_DTA, ffblk, sizeof(*ffblk));
  577.     memcpy(SDA_SDB, ffblk, sizeof(*SDA_SDB));
  578.     SDA_SDB->drive |= 0x80;
  579.     DTAtoDIR(ffblk);
  580.   }
  581.   return (regs->ax) ? 0xff00 : 0x0000;
  582. }
  583.  
  584. LOCAL BOOL ifs_closeall(INTREGS *regs)
  585. {
  586.   COMMAND(IFS_CLOSEALL);
  587.   iobufptr->length=2;
  588.   Transmit();
  589.   regs->ax=iobufptr->cmd;
  590.   return (regs->ax) ? 0xff00 : 0x0000;
  591. }
  592.  
  593.  
  594. LOCAL BOOL ifs_seekfromend(INTREGS *regs)
  595. {
  596.   SFT *sft=MK_FP(regs->es, regs->di);
  597.   DWORD nlen=(((DWORD) regs->cx) << 16L) | regs->dx;
  598.  
  599.   if ((!sft->handlect) || (sft->fsize < nlen)) {
  600.     regs->ax=0x05;
  601.     return 0xff00;
  602.   } else {
  603.     sft->fpos=sft->fsize-nlen;
  604.     regs->ax=sft->fpos & 0xffff;
  605.     regs->dx=sft->fpos >> 16;
  606.     return 0x0000;
  607.   }
  608. }
  609.  
  610. LOCAL BOOL ifs_extopen(INTREGS *regs)
  611. {
  612.   SFT *sft=MK_FP(regs->es, regs->di);
  613.   char *ptr;
  614.  
  615.   memset(sft, 0, sizeof(*sft));
  616.   sft->handlect=1; /*
  617.                      fake this to `1' because if the server exists
  618.                      on the same machine as the client, this sft
  619.                      NEEDS TO BE RESERVED!
  620.                    */
  621.   COMMAND(IFS_EXTOPEN);
  622.   *(int *) iobufptr->data     = *SDA_EXTOPEN_ACTION;
  623.   *(int *) (iobufptr->data+2) = *SDA_EXTOPEN_MODE;
  624.   *(int *) (iobufptr->data+4) = regs->wparam;
  625.   iobufptr->length=6;
  626.   ptr=iobufptr->data+iobufptr->length;
  627.   SPARAM(SDA_FN1);
  628.   *ptr=remote;
  629.   Transmit();
  630.   sft->handlect=0;
  631.   regs->ax=iobufptr->cmd;
  632.   if (regs->ax == 0) {
  633.     regs->ax=*(int *) (iobufptr->data);   /* file handle  */
  634.     regs->cx=*(int *) (iobufptr->data+2); /* result flags */
  635.     sft->open_mode=*SDA_EXTOPEN_MODE & 0x7f;
  636.     sft->attr     =regs->wparam;
  637.     sft->dev_info=0x8040 | (local-'A'+1); /* force drive Z */
  638.     sft->ftime    = *(int *) (iobufptr->data+4);
  639.     sft->fdate    = *(int *) (iobufptr->data+6);
  640.     sft->fsize    = *(long *) (iobufptr->data+8);
  641.     NAMEtoFCB(SDA_FN1, sft->fcb_name);
  642.  
  643.     sft->dir_sector=*(int *) iobufptr->data; /* this is really the file handle */
  644.   }
  645.   return (iobufptr->cmd) ? 0xff00 : 0x0000;
  646. }
  647.  
  648. /*
  649.   chktype = 1-> validate using SDA->FN1
  650.             2-> validate using ES:DI --> SFT
  651. */
  652. #define IFSNULL {NULL, 0}
  653.  
  654. LOCAL struct {
  655.   BOOL (*fn)(INTREGS *regs);
  656.   char chktype;
  657. } fnTable[] = {
  658.                   IFSNULL,
  659.                   {ifs_rmdir, 1},
  660.                   IFSNULL,
  661.                   {ifs_mkdir, 1},       /* make dir */
  662.                   IFSNULL,
  663.                   {ifs_chdir, 1},       /* change dir */
  664.                   {ifs_closefile, 2},   /* close file */
  665.                   {ifs_commitfile, 2},  /* commit file */
  666.                   {ifs_readfile, 2},    /* read */
  667.                   {ifs_writefile, 2},   /* write */
  668.                   {ifs_lockfile, 2},    /* lock  */
  669.                   {ifs_unlockfile, 2},  /* unlock */
  670.                   {ifs_getspace, 1},    /* get free disk space */
  671.                   IFSNULL,
  672.                   {ifs_setattr, 1},     /* set file attr */
  673.                   {ifs_getattr, 1},     /* get file attr */
  674.                   IFSNULL,
  675.                   {ifs_renamefile, 1},  /* rename file */
  676.                   IFSNULL,
  677.                   {ifs_deletefile, 1},  /* delete file */
  678.                   IFSNULL,
  679.                   IFSNULL,
  680.                   {ifs_openfile, 1},    /* open file */
  681.                   {ifs_createfile, 1},  /* create file */
  682.                   IFSNULL,
  683.                   IFSNULL,
  684.                   IFSNULL,
  685.                   {ifs_findfirst, 1},   /* find first */
  686.                   {ifs_findnext, 1},    /* find next */
  687.                   {ifs_closeall, 1},    /* close all files for a process */
  688.                   IFSNULL,
  689.                   IFSNULL,
  690.                   IFSNULL,
  691.                   {ifs_seekfromend, 1}, /* seek from end of file */
  692.                   {ifs_closeall, 1},    /* process terminate, close all files */
  693.                   IFSNULL,
  694.                   IFSNULL,
  695.                   IFSNULL,
  696.                   IFSNULL,
  697.                   IFSNULL,
  698.                   IFSNULL,
  699.                   IFSNULL,
  700.                   IFSNULL,
  701.                   IFSNULL,
  702.                   IFSNULL,
  703.                   IFSNULL,
  704.                   {ifs_extopen, 1}      /* extended open */
  705.                 };
  706. /*
  707.   return
  708.     0xffff: chain
  709.     0x0000: normal return
  710.     0xff00: normal return / set carry
  711. */
  712.  
  713. int dispatch(INTREGS *regs)
  714. {
  715.   int fn=regs->ax >> 8,
  716.       subfn=regs->ax & 0xff;
  717.   int ii;
  718.  
  719.   remote=0;
  720.   regs->flags &= ~1;
  721.  
  722.   if ((fn == 0x11)
  723.      && (subfn < sizeof(fnTable)/sizeof(*fnTable))
  724.      && fnTable[subfn].fn) {
  725.     switch (fnTable[subfn].chktype) {
  726.       case 1:
  727.         for (ii=0; (ii < CDS_ct); ii++) {
  728.           if (DRIVE_XLAT_TABLE[ii]) {
  729.             CDS *s=(CDS *) (CDS_base+CDS_size*ii);
  730.             if (!strnicmp((*SDA_DRIVE_CDSPTR)->cwd, s->cwd, s->bs)) {
  731.               local='A'+ii;
  732.               remote=DRIVE_XLAT_TABLE[ii];
  733.               break;
  734.             }
  735.           }
  736.         }
  737.         break;
  738.       case 2:
  739.         {
  740.           SFT *sft=MK_FP(regs->es, regs->di);
  741.           for (ii=0; (ii < CDS_ct); ii++) {
  742.             if (DRIVE_XLAT_TABLE[ii]) {
  743.               if ((sft->dev_info & 0x3f) == (ii+1)) {
  744.                 local='A'+ii;
  745.                 remote=DRIVE_XLAT_TABLE[ii];
  746.                 break;
  747.               }
  748.             }
  749.           }
  750.         }
  751.         break;
  752.     }
  753.     if (remote) {
  754.       int ret;
  755.       ret=fnTable[subfn].fn(regs);
  756.       return ret;
  757.     } else
  758.       return 0xffff;
  759.   } else
  760.     return 0xffff;
  761. }
  762.  
  763. /*
  764.   transmit buffer
  765.   wait for response
  766.   if no response in 5 sec, assume trasmission lost, and resend it.
  767. */
  768.  
  769. WORD Transmit(void)
  770. {
  771.   int state=0;
  772.   XMITBUF *newbuf = ((iobufptr == iobuf1) ? iobuf2 : iobuf1);
  773.   char *ptr;
  774.   int byte=0, last;
  775.   int retry=5,   /* allow up to 5 retries on send */
  776.       resend=1;
  777.   int len=0;
  778.  
  779.   iobufptr->packetID[0]='K';
  780.   iobufptr->packetID[1]='Y';
  781.   iobufptr->length+=sizeof(*iobufptr);
  782.   iobufptr->notlength=~iobufptr->length;
  783.  
  784.   iobufptr->process_id=*SDA_CURR_PSP;
  785.   iobufptr->crc32=0;
  786.   iobufptr->crc32=crc32(0, iobufptr, iobufptr->length);
  787.  
  788.   do {
  789.     if (resend) {
  790.       CommIO_FlushBuffer();
  791.       CommIO_TransmitLoop(iobufptr, iobufptr->length);
  792.       /* while (CommIO_TransmitPending()); */
  793.       if (retry)
  794.         retry--;
  795.       state=0;
  796.       resend=0;
  797.     }
  798.     last=byte;
  799.     byte=CommIO_WaitByteLoop(73); /* allow 4 second timeout */
  800.     if (byte < 0) {
  801.       resend=1;
  802.       IFS_stat.timeout++;
  803.     } else {
  804.       switch (state) {
  805.         case 0:
  806.           if (byte == 'L')
  807.             state++;
  808.           break;
  809.         case 1:
  810.           if ((last == 'L') && (byte == 'Y')) {
  811.             state++;
  812.             ptr  = (void *) newbuf;
  813.             *(ptr++)=last;
  814.             *(ptr++)=byte;
  815.             len=2;
  816.           } else
  817.             resend=1;
  818.           break;
  819.         case 2:
  820.           *(ptr++)=byte;
  821.           len++;
  822.           if ((len == 6) && (newbuf->length != ~newbuf->notlength)) {
  823.             resend=1;
  824.             IFS_stat.lenfail++;
  825.           } else if (len == newbuf->length) {
  826.             DWORD oldcrc=newbuf->crc32;
  827.             newbuf->crc32=0;
  828.             if (crc32(0, newbuf, newbuf->length) != oldcrc) {
  829.               resend=1;
  830.               IFS_stat.crcfail++;
  831.             } else
  832.               retry=-1; /* flag that we've completed */
  833.           }
  834.       }
  835.     }
  836.   } while (retry > 0);
  837.   CommIO_FlushBuffer();
  838.   iobufptr=newbuf;
  839.   if (retry == 0)
  840.     iobufptr->cmd=0x15;
  841.   else
  842.     IFS_stat.valid += iobufptr->length;
  843.   return iobufptr->cmd;
  844. }
  845.  
  846. LOCAL char *options[]={"/speed=",
  847.                "/com1",
  848.                "/com2",
  849.                "/com3",
  850.                "/com4",
  851.                "/irq=",
  852.                "/port=",
  853.                "/remove",
  854.                "/intno=",
  855.                NULL};
  856.  
  857. void main(int argc, char **argv)
  858. {
  859.   char *ptr;
  860.   long  speed=19200;
  861.   int   com=-1,
  862.         irq=-1,
  863.         port=-1,
  864.         intno=FindUnusedInt();
  865.   BOOL  removeflag=FALSE;
  866.   int   opt;
  867.   int   RIFS=FindRIFS();
  868.  
  869.   if ((_osmajor != 0x03) && (_osmajor < 0x05)) {
  870.     fprintf(stderr, "RIFS Client Module is only compatable with DOS 3.x,\n"
  871.                     "and DOS >= 5.x (not DOS 4.x).\n");
  872.     exit(1);
  873.   }
  874.   {
  875.     /*
  876.       1st lose the environment
  877.     */
  878.     unsigned seg=*(WORD *) MK_FP(_psp, 0x2c);
  879.     freemem(seg);
  880.   }
  881.   /*
  882.     init variables
  883.   */
  884.   ArgInit(argc, argv);
  885.  
  886.   while ((opt=GetOption(options)) != -1) {
  887.     switch (opt) {
  888.       case 0:
  889.         speed=strtol(GetArg(), &ptr, 0x0a);
  890.         if (speed == 0)
  891.           ArgError("speed out of range [2..115200]");
  892.         if (115200L % speed)
  893.           speed=115200/(115200/speed+1);
  894.         break;
  895.       case 1:
  896.       case 2:
  897.       case 3:
  898.       case 4:
  899.         com=opt;
  900.         break;
  901.       case 5:
  902.         irq=strtol(GetArg(), &ptr, 0x10);
  903.         if ((irq < 0) || (irq > 0x0f))
  904.           ArgError("IRQ out of range [0..0f]");
  905.         break;
  906.       case 6:
  907.         port=strtol(GetArg(), &ptr, 0x10);
  908.         break;
  909.       case 7:
  910.         removeflag=1;
  911.         break;
  912.       case 8:
  913.         intno=strtol(GetArg(), &ptr, 0x10);
  914.         break;
  915.     }
  916.   }
  917.  
  918.   if (removeflag) {
  919.     struct REGPACK regs;
  920.  
  921.     if (RIFS) {
  922.       regs.r_ax=0;
  923.       intr(RIFS, ®s);
  924.     }
  925.     if (!RIFS || (regs.r_ax != 0x1234)) {
  926.       printf("RCLIENT not found\n");
  927.       exit(1);
  928.     } else {
  929.       regs.r_ax=1;
  930.       intr(RIFS, ®s);
  931.       printf("RCLIENT removed from memory\n");
  932.       exit(0);
  933.     }
  934.   } else if (RIFS) {
  935.     struct REGPACK regs;
  936.     regs.r_ax=RCLIENT_QUERY;
  937.     intr(RIFS, ®s);
  938.     if (regs.r_ax == 0x1234) {
  939.       printf("RCLIENT already loaded\n");
  940.       exit(1);
  941.     }
  942.     regs.r_ax=RSERVER_QUERY;
  943.     intr(RIFS, ®s);
  944.     if (regs.r_ax == 0x4321) {
  945.       printf("RSERVER is loaded\n");
  946.       exit(1);
  947.     }
  948.   }
  949.   if ((com < 0) && ((irq < 0) || (port < 0))) {
  950.     for (com=1; com <= 4; com++)
  951.       if (*(WORD *) (MK_FP(0x40, 2*(com-1))))
  952.         break;
  953.     if (com > 4)
  954.       ArgError("cannot find available com port");
  955.   }
  956.   if (!intno)
  957.     ArgError("cannot find unused user interrupt");
  958.   InitClient(intno);
  959.   CommIO_Initialize(com, STOP_1 | WORD_8 | PARITY_NONE, speed, 0, port);
  960.   printf("Client initialized on port (%d) at (%ld)\n", com, speed);
  961.   {
  962.     MCB *mcb=MK_FP(_psp-1, 0);
  963.     keep(0, mcb->size);
  964.   }
  965. }
  966.  
  967. /*
  968.   map local drive [local] ('A'..'Z') to remote drive [remote] ('A'..'Z')
  969. */
  970. BOOL RemapDrive(BYTE local, BYTE remote)
  971. {
  972.   CDS *cds;
  973.  
  974.   if (isalpha(remote) && isalpha(local)) {
  975.     local=toupper(local)-'A';
  976.     remote=toupper(remote);
  977.     DRIVE_XLAT_TABLE[local]=remote;
  978.     cds=(CDS *) (CDS_base + local * CDS_size);
  979.     memset(cds, 0, CDS_size);
  980.     strcpy(cds->cwd, " :\\");
  981.     cds->cwd[0]=local+'A';
  982.     cds->flags = NETWORK | PHYSICAL;
  983.     cds->bs    = strlen(cds->cwd)-1;
  984.     return TRUE;
  985.   } else
  986.     return FALSE;
  987. }
  988.  
  989. /*
  990.   return drive map to original (startup)
  991. */
  992. BOOL UnmapDrive(BYTE dv)
  993. {
  994.   CDS *origcds,
  995.       *cds;
  996.  
  997.   if (isalpha(dv)) {
  998.     dv=toupper(dv)-'A';
  999.     DRIVE_XLAT_TABLE[dv]=0;
  1000.     cds     =(CDS *) (CDS_base + dv * CDS_size);
  1001.     origcds =(CDS *) (CDS_init + dv * CDS_size);
  1002.     memcpy(cds, origcds, CDS_size);
  1003.     return TRUE;
  1004.   }
  1005.   return FALSE;
  1006. }
  1007.  
  1008. BOOL UnmapAll(void)
  1009. {
  1010.   memcpy(CDS_base, CDS_init, CDS_size);
  1011.   return TRUE;
  1012. }
  1013.  
  1014. void UserInt(INTREGS *regs)
  1015. {
  1016.   /*
  1017.     RCLIENT functions...
  1018.   */
  1019.   regs->flags &= ~1;
  1020.   switch (regs->ax) {
  1021.     case RCLIENT_QUERY: /* query client / server */
  1022.       regs->ax=0x1234;
  1023.       break;
  1024.     case RCLIENT_UNLOAD: /* unload */
  1025.       uninit();
  1026.       freemem(_psp);
  1027.       break;
  1028.     case RCLIENT_REMAP: /* remap (local BH == remote BL) */
  1029.       regs->ax=RemapDrive(regs->bx >> 8, regs->bx & 0xff);
  1030.       break;
  1031.     case RCLIENT_UNMAP: /* unmap BL */
  1032.       regs->ax=UnmapDrive(regs->bx & 0xff);
  1033.       break;
  1034.     case RCLIENT_UNMAPALL: /* unmap ALL */
  1035.       regs->ax=UnmapAll();
  1036.       break;
  1037.     case RCLIENT_GETXLAT: /* return translation table */
  1038.       regs->es=FP_SEG(DRIVE_XLAT_TABLE);
  1039.       regs->bx=FP_OFF(DRIVE_XLAT_TABLE);
  1040.       break;
  1041.     case RCLIENT_GETSTAT:
  1042.       regs->es=FP_SEG(&IFS_stat);
  1043.       regs->bx=FP_OFF(&IFS_stat);
  1044.       IFS_stat.totalsent=total_sent;
  1045.       IFS_stat.totalrcvd=total_rcvd;
  1046.       IFS_stat.stackused=ifs0_GetStackUsed();
  1047.       break;
  1048.     case RCLIENT_GETPORTXLAT:
  1049.       regs->es=FP_SEG(portmapped);
  1050.       regs->bx=FP_OFF(portmapped);
  1051.       regs->cx=sizeof(portmapped)/sizeof(portmapped[0]);
  1052.     default:
  1053.       regs->flags |= 1;
  1054.   }
  1055. }
  1056.